package org.chartsy.atr;
import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.Stroke;
import java.text.DecimalFormat;
import java.util.LinkedHashMap;
import org.chartsy.main.ChartFrame;
import org.chartsy.main.chart.Indicator;
import org.chartsy.main.data.DataItem;
import org.chartsy.main.data.Dataset;
import org.chartsy.main.utils.DefaultPainter;
import org.chartsy.main.utils.Range;
import org.chartsy.main.utils.SerialVersion;
import org.openide.nodes.AbstractNode;
/**
*
* @author Viorel
*/
public class AverageTrueRange
extends Indicator
{
private static final long serialVersionUID = SerialVersion.APPVERSION;
public static final String ATR = "atr";
private IndicatorProperties properties;
public AverageTrueRange()
{
super();
properties = new IndicatorProperties();
}
public @Override String getName()
{
return "ATR";
}
public @Override String getLabel()
{
return properties.getLabel() + " (" + properties.getPeriod() + ")";
}
public @Override String getPaintedLabel(ChartFrame cf)
{
return getLabel();
}
public @Override Indicator newInstance()
{
return new AverageTrueRange();
}
public @Override LinkedHashMap getHTML(ChartFrame cf, int i)
{
LinkedHashMap ht = new LinkedHashMap();
DecimalFormat df = new DecimalFormat("#,##0.00");
double[] values = getValues(cf, i);
String[] labels = {"ATR:"};
ht.put(getLabel(), " ");
if (values.length > 0) {
Color[] colors = getColors();
for (int j = 0; j < values.length; j++) {
ht.put(getFontHTML(colors[j], labels[j]),
getFontHTML(colors[j], df.format(values[j])));
}
}
return ht;
}
public @Override void paint(Graphics2D g, ChartFrame cf, Rectangle bounds)
{
Dataset atrDataset = visibleDataset(cf, ATR);
if (atrDataset != null)
{
if (maximized)
{
Range range = getRange(cf);
DefaultPainter.line(g, cf, range, bounds, atrDataset, properties.getColor(), properties.getStroke());
}
}
}
public @Override void calculate()
{
Dataset mainDataset = getDataset();
if (mainDataset != null && !mainDataset.isEmpty())
{
addDataset(ATR, getATRDataset(mainDataset));
}
}
public @Override boolean hasZeroLine()
{
return false;
}
public @Override boolean getZeroLineVisibility()
{
return false;
}
public @Override Color getZeroLineColor()
{
return null;
}
public @Override Stroke getZeroLineStroke()
{
return null;
}
public @Override boolean hasDelimiters()
{
return false;
}
public @Override boolean getDelimitersVisibility()
{
return false;
}
public @Override double[] getDelimitersValues()
{
return new double[] {};
}
public @Override Color getDelimitersColor()
{
return null;
}
public @Override Stroke getDelimitersStroke()
{
return null;
}
public @Override Color[] getColors()
{
return new Color[]
{
properties.getColor()
};
}
public @Override double[] getValues(ChartFrame cf)
{
Dataset atrDataset = visibleDataset(cf, ATR);
int i = atrDataset.getLastIndex();
if (atrDataset.getDataItem(i) != null)
return new double[]
{
atrDataset.getCloseAt(i)
};
return new double[] {0};
}
public @Override double[] getValues(ChartFrame cf, int i)
{
Dataset atrDataset = visibleDataset(cf, ATR);
if (atrDataset.getDataItem(i) != null)
return new double[]
{
atrDataset.getCloseAt(i)
};
return new double[] {0};
}
public @Override boolean getMarkerVisibility()
{
return properties.getMarker();
}
public @Override AbstractNode getNode()
{
return new IndicatorNode(properties);
}
private Dataset getATRDataset(Dataset dataset)
{
int period = properties.getPeriod();
int count = dataset.getItemsCount();
Dataset result = Dataset.EMPTY(count);
double[] trueRange = new double[count]; // daily TR
for (int i = 0; i < count; i++)
{
double high = dataset.getHighAt(i);
double low = dataset.getLowAt(i);
if (i == 0)
{
trueRange[i] = high - low; // first TR value = high - low
}
else
{
double prevClose = dataset.getCloseAt(i - 1);
trueRange[i] = Math.max( Math.abs( low - prevClose ), Math.max( high - low, Math.abs( high - prevClose ) ) );
if (i >= period - 1)
{
double atrValue = 0;
for (int j = 0; j < period; j++)
{
atrValue += trueRange[i - j];
}
atrValue /= (double)period;
result.setDataItem(i, new DataItem(dataset.getTimeAt(i), atrValue));
}
}
}
return result;
}
public @Override Double[] getPriceValues(ChartFrame cf)
{
Range range = getRange(cf);
if (range.getUpperBound() < 1)
{
double max = Math.ceil(range.getUpperBound() * 10) / 10;
double min = Math.floor(range.getLowerBound() * 10) / 10;
double diff = (max - min) * 100;
int count = (int) (diff / 10);
Double[] values = new Double[count];
for (int i = 0; i < count; i++)
values[i] = new Double(min + ((double) i)/10);
return values;
}
else if (range.getUpperBound() > 1 && range.getUpperBound() < 10)
{
double max = Math.ceil(range.getUpperBound());
double step = 0.5;
int count = (int) (max / step) + 1;
Double[] values = new Double[count];
for (int i = 0; i < count; i++)
values[i] = new Double((double) (i * step));
return values;
}
else
{
double max = Math.ceil(range.getUpperBound());
int step = 5;
int count = (int) (max / step) + 1;
Double[] values = new Double[count];
for (int i = 0; i < count; i++)
values[i] = new Double((double) (i * step));
return values;
}
}
}